﻿using System;
using System.ComponentModel;
using System.Linq.Expressions;
using SSG.Tools;

namespace SSG.Model
{
    /// <summary>
    /// Filter
    /// </summary>
    [Serializable]
    public class NameFilter : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private bool _namesWithNumber = false;
        private bool _namesWithRunway = false;
        private bool _modeExclude = false;
        private bool _modeInclude = false;
        private bool _modeIgnore = true;
        private bool _filteredAsComment = false;

        /// <summary>
        /// Summary String
        /// </summary>
        public string Summary
        {
            get
            {
                string s = "";
                if (this.ModeIgnore) s += Properties.Resources.NameFilterIgnore;
                if (this.ModeInclude) s += Properties.Resources.NameFilterInclude;
                if (this.ModeExclude) s += Properties.Resources.NameFilterExclude;
                if (this.NamesWithNumber) s += ", " + Properties.Resources.NameFilterNamesWithNumber;
                if (this.NamesWithRunway) s += ", " + Properties.Resources.NameFilterNamesWithRunway;
                return s;
            }
        }


        /// <summary>
        /// Names with number?
        /// </summary>
        public bool NamesWithNumber
        {
            get { return this._namesWithNumber; }
            set
            {
                if (this._namesWithNumber == value) return;
                this._namesWithNumber = value;
                this.ForceIgnoreIfRequired();
                this.OnPropertyChanged(() => this.NamesWithNumber);
            }
        }

        /// <summary>
        /// Names with runway?
        /// </summary>
        public bool NamesWithRunway
        {
            get { return this._namesWithRunway; }
            set
            {
                if (this._namesWithRunway == value) return;
                this._namesWithRunway = value;
                this.ForceIgnoreIfRequired();
                this.OnPropertyChanged(() => this.NamesWithRunway);
            }
        }

        /// <summary>
        /// Filtered elements written as comments?
        /// </summary>
        public bool FilteredAsComments
        {
            get { return this._filteredAsComment; }
            set
            {
                if (this._filteredAsComment == value) return;
                this._filteredAsComment = value;
                this.OnPropertyChanged(() => this.FilteredAsComments);
            }
        }

        /// <summary>
        /// Exclude mode?
        /// </summary>
        public bool ModeExclude
        {
            get { return this._modeExclude; }
            set
            {
                if (this._modeExclude == value) return;
                this.SetDefaultMode(value);
                this._modeExclude = value;
                this.OnPropertyChanged(() => this.ModeExclude);
            }
        }

        /// <summary>
        /// Include mode?
        /// </summary>
        public bool ModeInclude
        {
            get { return this._modeInclude; }
            set
            {
                if (this._modeInclude == value) return;
                this.SetDefaultMode(value);
                this._modeInclude = value;
                this.OnPropertyChanged(() => this.ModeExclude);
            }
        }

        /// <summary>
        /// Ignore mode?
        /// </summary>
        public bool ModeIgnore
        {
            get { return this._modeIgnore; }
            set
            {
                if (this._modeIgnore == value) return;
                this.SetDefaultMode(value);
                this._modeIgnore = value;
                this.OnPropertyChanged(() => this.ModeIgnore);
            }
        }

        /// <summary>
        /// String with number
        /// </summary>
        /// <param name="candidate"></param>
        /// <returns></returns>
        public bool ContainsNumber(string candidate)
        {
            return !String.IsNullOrEmpty(candidate) && System.Text.RegularExpressions.Regex.IsMatch(candidate, @"\d");
        }

        /// <summary>
        /// Set a default mode
        /// </summary>
        /// <param name="value"></param>
        private void SetDefaultMode(bool value)
        {
            this._modeExclude = false;
            this._modeInclude = false;
            this._modeIgnore = !value;
            this.OnPropertyChanged(() => this.ModeIgnore);
        }

        /// <summary>
        /// Force, since no filter is selected
        /// </summary>
        private void ForceIgnoreIfRequired()
        {
            if (this._namesWithNumber) return;
            if (this._namesWithRunway) return;
            this.SetDefaultMode(false);
        }

        /// <summary>
        /// Property changed handling.
        /// </summary>
        /// <param name="property"></param>
        protected virtual void OnPropertyChanged<T>(Expression<Func<T>> property)
        {
            string propertyName = ObjectTools.GetPropertyName(property);
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }

        /// <summary>
        /// Meaningful representation
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return this.Summary;
        }
    }
}